package com.mxpio.erp.mes.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.mxpio.erp.common.enums.CommonEnums;
import com.mxpio.erp.common.mes.entity.ManufactureWorkOrder;
import com.mxpio.erp.common.mes.entity.ManufactureWorkOrderTask;
import com.mxpio.erp.common.mes.pojo.ManufactureWorkOrderVo;
import com.mxpio.erp.common.mes.service.ManufactureWorkOrderService;
import com.mxpio.erp.common.technology.entity.Item;
import com.mxpio.erp.common.technology.entity.ItemQualityProp;
import com.mxpio.erp.common.workshop.entity.ManufactureOrder;
import com.mxpio.erp.common.workshop.entity.ManufactureOrderRoute;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.Operator;
import com.mxpioframework.jpa.query.Order;
import com.mxpioframework.system.service.impl.BaseServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

@Service
public class ManufactureWorkOrderServiceImpl extends BaseServiceImpl<ManufactureWorkOrder> implements ManufactureWorkOrderService {
    @Override
    @Transactional
    public Result<?> manufactureOrderDispatch(ManufactureWorkOrderVo batchInfoVo) {
        String bizNo = batchInfoVo.getBizNo();
        ManufactureOrder mo = JpaUtil.linq(ManufactureOrder.class).equal("bizNo", bizNo).findOne();
        if (mo==null){
            return Result.error("未查询到对应的生产订单！请检查请求参数。");
        }
        //查询订单工艺路路线
        Criteria orderRouteCri = Criteria.create();
        orderRouteCri.addOrder(new Order("processOrder",false));
        List<ManufactureOrderRoute> orderRouteList = JpaUtil.linq(ManufactureOrderRoute.class).equal("bizNo", bizNo).where(orderRouteCri).list();
        if (orderRouteList.isEmpty()){
            return Result.error("订单工艺路线为空");
        }


        ItemQualityProp inspectRule = JpaUtil.linq(ItemQualityProp.class).equal("propType", "item").equal("code", mo.getProductItemCode()).findOne();
        if (inspectRule==null){
            //return Result.error("未维护订单产品的成品检验规则，请先维护数据。");
            inspectRule = new ItemQualityProp();
        }


        Criteria order = Criteria.create();
        order.addOrder(new Order("batchOrder",true));
        List<ManufactureWorkOrder> batchInfoList = JpaUtil.linq(ManufactureWorkOrder.class).equal("bizNo", bizNo).where(order).list();
        Integer preInvestNum = 0;//已投产数量
        Integer maxSerialNumber = null;
        if (!batchInfoList.isEmpty()){
            preInvestNum = batchInfoList.stream().mapToInt(ManufactureWorkOrder::getBatchNum).reduce(0, Integer::sum);
            maxSerialNumber = batchInfoList.get(0).getBatchOrder();
        }

        int lastNum = mo.getOrderQuantity().intValue() - preInvestNum ;
        if (lastNum < batchInfoVo.getCurrentNum()) {
            return Result.error("订单数量："+mo.getOrderQuantity().toPlainString()+"，已投产数量："+preInvestNum+"，当前投入量："+batchInfoVo.getCurrentNum()+"超过最大可投数量："+lastNum+"。");
        }
        //首次拆批
        if (preInvestNum==0
                && StringUtils.equals(inspectRule.getFirstInspectNeeded(), CommonEnums.YesNo.YES.getCode())
                && inspectRule.getFirstInspectNum()<batchInfoVo.getCurrentNum()){
            return Result.error("首次下发操作，工单数量不能小于首检数量。");
        }
        ManufactureWorkOrder batchInfo = new ManufactureWorkOrder();

        batchInfo.setBizNo(bizNo);
        batchInfo.setBatchNum(batchInfoVo.getCurrentNum());
        batchInfo.setMainWorkshop(mo.getMainWorkshop());//取生产订单
        batchInfo.setWorkCenterCode(mo.getWorkCenterCode());

        if (preInvestNum==0){//首次下发
            batchInfo.setFirstInspectNeeded(inspectRule.getFirstInspectNeeded());
            batchInfo.setFirstInspectNum(inspectRule.getFirstInspectNum());
            batchInfo.setFirstInspectType(inspectRule.getFirstInspectType());
        }
        //可能首次下发即全部订单数量的情况
        if (StringUtils.equals(inspectRule.getFinalInspectNeeded(), CommonEnums.YesNo.YES.getCode())){
            int finalInspectNum = inspectRule.getFirstInspectNum();
            if ((lastNum - batchInfoVo.getCurrentNum()) < finalInspectNum){//
                batchInfo.setFinalInspectNeeded(CommonEnums.YesNo.YES.getCode());
                batchInfo.setFinalInspectType(inspectRule.getFinalInspectType());
                if (batchInfoVo.getCurrentNum()>finalInspectNum){
                    batchInfo.setFinalInspectNum(batchInfoVo.getCurrentNum()-finalInspectNum);
                }else{
                    batchInfo.setFinalInspectNum(batchInfoVo.getCurrentNum());
                }
            }
        }else{
            batchInfo.setFinalInspectNeeded(CommonEnums.YesNo.NO.getCode());
        }
        if(maxSerialNumber ==null){
            batchInfo.setBatchOrder(1);
        }else{
            batchInfo.setBatchOrder(maxSerialNumber+1);
        }
        batchInfo.setBatchCode(mo.getBizNo()+"_"+String.format("%04d",batchInfo.getBatchOrder()));
        this.save(batchInfo);//保存工单
        //根据工单数量和订单工艺路线，生成具体的sn工序任务
        Item productItem = JpaUtil.linq(Item.class).equal("itemCode", mo.getProductItemCode()).findOne();
        for (int i = 0; i < batchInfo.getBatchNum(); i++) {
            String taskSn = batchInfo.getBatchCode()+"_"+String.format("%04d",i+1);
            int routeLoopIndex = 0;
            boolean firstInspectFlag = false;
            if (StringUtils.equals(batchInfo.getFirstInspectNeeded(), CommonEnums.YesNo.YES.getCode())){
                if (i<batchInfo.getFirstInspectNum()){
                    firstInspectFlag = true;
                }
            }
            boolean finalInspectFlag = false;
            if (StringUtils.equals(batchInfo.getFinalInspectNeeded(), CommonEnums.YesNo.YES.getCode())){
                if (i<batchInfo.getFinalInspectNum()){
                    finalInspectFlag = true;
                }
            }
            for (ManufactureOrderRoute route:orderRouteList){
                routeLoopIndex++;
                ManufactureWorkOrderTask snTask = new ManufactureWorkOrderTask();
                snTask.setBizNo(batchInfo.getBizNo());
                snTask.setBatchCode(batchInfo.getBatchCode());
                snTask.setSnCode(taskSn );
                snTask.setTaskCode(taskSn+"_"+String.format("%02d",routeLoopIndex));
                if (firstInspectFlag){
                    snTask.setFirstInspectNeeded(batchInfo.getFirstInspectNeeded());
                    snTask.setFirstInspectType(batchInfo.getFirstInspectType());
                }else if (finalInspectFlag){
                    snTask.setFinalInspectNeeded(batchInfo.getFinalInspectNeeded());
                    snTask.setFinalInspectType(batchInfo.getFinalInspectType());
                }
                snTask.setProcCode(route.getProcessCode());
                snTask.setProcOrder(route.getProcessOrder());
                snTask.setProcGroupCode(route.getProcGroupCode());
                snTask.setProcGroupName(route.getProcGroupName());
                snTask.setPreparationTime(route.getPreparationTime());
                snTask.setSinglePieceTime(route.getSinglePieceTime());
                snTask.setRoutProcId(route.getRoutProcId());
                snTask.setItemCode(productItem.getItemCode());
                snTask.setItemName(productItem.getItemName());
                snTask.setItemSpec(productItem.getItemSpec());
                snTask.setUnitCode(productItem.getUnitCode());

                JpaUtil.save(snTask);
            }
        }
        return Result.OK();
    }

    @Override
    @Transactional(readOnly = true)//关联生产订单已下发数量
    public void handleDispatchNum(List<ManufactureOrder> content) {
        if (CollectionUtil.isNotEmpty(content)){
            for (ManufactureOrder mo:content){
                Criteria criteria = Criteria.create();
                criteria.addCriterion("bizNo", Operator.EQ,mo.getBizNo());
                List<ManufactureWorkOrder> list = this.list(ManufactureWorkOrder.class, criteria);
                if (list.isEmpty()){
                    mo.setPreInvestNum(BigDecimal.ZERO);
                }else{
                    int preInvestNum = list.stream().mapToInt(ManufactureWorkOrder::getBatchNum).reduce(0, Integer::sum);
                    mo.setPreInvestNum(new BigDecimal(preInvestNum));
                }
            }
        }
    }
}

